package com.example.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.*;
import com.example.demo.entity.vo.AchieveVo;
import com.example.demo.exception.bizException.BizException;
import com.example.demo.mapper.AchieveMapper;
import com.example.demo.service.*;
import com.example.demo.util.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
* <p>
*  服务实现类
* </p>
*
* @author cy
* @since 2020-08-01
*/
@Slf4j
@Service
public class AchieveServiceImpl extends ServiceImpl<AchieveMapper, Achieve> implements AchieveService {

    @Autowired
    private UserService userService;

    @Autowired
    private InformationService informationService;

    @Autowired
    private FileService fileService;

    @Autowired
    private AAccessoryService aAccessoryService;

    @Autowired
    private CollectService collectService;

    @Override
    public Page<AchieveVo> listAchievesByPage(int page, int pageSize, Integer userId,String  achieveName,Integer  state,String  achieveType,String achieveIndustry) {
        log.info("正在执行分页查询achieve: page = {} pageSize = {} userId = {} achieveName={} state={} achieveType={}",page,pageSize,userId,achieveName,state, achieveType);
        QueryWrapper<Achieve> queryWrapper =  new QueryWrapper<Achieve>().eq(userId!=null,"u_id",userId).
                eq(state!=null,"state",state)
                .eq(achieveType.length()!=0,"achieve_type",achieveType)
                .and(achieveName.length()!=0,wrapper->wrapper.like("achieve_name",achieveName))
                .eq(achieveIndustry.length() !=0 ,"achieve_industry",achieveIndustry)
                .and(achieveName.length()!=0,wrapper->wrapper.like("achieve_name",achieveName))
                .or(achieveName.length()!=0,wrapper->wrapper.like("achieve_leader",achieveName))
                .orderByDesc("achieve_name");
        Page<Achieve> result = super.page(new Page<>(page, pageSize),queryWrapper);
        log.info("分页查询achieve完毕: 结果数 = {} ",result.getRecords().size());
        //转为vo，插入用户数据
        Page<AchieveVo> voPage=new Page<>();
        List<AchieveVo> voList=new ArrayList<>(result.getRecords().size());
        for(Achieve achieve:result.getRecords()){
            AchieveVo achieveVo=new AchieveVo();
            achieveVo.setAchieve(achieve);
            //去除密码
            QueryWrapper<User> userQueryWrapper=new QueryWrapper<User>().select(User.class,info-> !"password".equals(info.getColumn())).
                    eq("user_id",achieve.getUId());
            achieveVo.setUser(userService.getByQueryWrapper(userQueryWrapper));
            voList.add(achieveVo);
        }
        BeanUtils.copyProperties(result,voPage);
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public AchieveVo getAchieveById(int id) {
        log.info("正在查询achieve中id为{}的数据",id);
        Achieve achieve = super.getById(id);
        log.info("查询id为{}的achieve{}",id,(null == achieve?"无结果":"成功"));
        AchieveVo applyVo=new AchieveVo();
        applyVo.setAchieve(achieve);
        assert achieve != null;
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<User>().select(User.class,info-> !"password".equals(info.getColumn())).
                eq("user_id",achieve.getUId());
        applyVo.setUser(userService.getByQueryWrapper(userQueryWrapper));
        return applyVo;
    }

    @Override
    public Achieve getJustAchieveById(int id) {
        Achieve achieve = super.getById(id);
        return achieve;
    }

    @Override
    public Achieve getAchieveByAchieveNameAndAchieveLeader(String achieveName, String achieveLeader) {
        return super.getOne(new QueryWrapper<Achieve>().eq("achieve_name",achieveName).eq("achieve_leader",achieveLeader));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int checkAchieve(Achieve achieve ) {
        log.info("achieve中id为{}正在通过审核",achieve.getAchieveId());
        Achieve inAchieve=super.getById(achieve.getAchieveId());
        //设置给用户的消息通知
        Information information=new Information();
        information.setTime(LocalDateTime.now());
        information.setUserId(inAchieve.getUId());
        //判断需求审核状态
        if(achieve.getState()== Demand.NO_PASS){
            information.setMessage("尊敬的用户您好，您的一个成果审核未通过，您可以对成果内容进行修改后再次提交申请或者联系管理员。");
        }else if(achieve.getState()==Demand.PASS){
            information.setMessage("尊敬的用户您好，您的一个成果审核已通过。");
        }else {
            throw new BizException("成果状态错误");
        }
        if (super.updateById(achieve)) {
            informationService.insertInformation(information);
            log.info("审核id为{}的achieve成功",achieve.getAchieveId());
            return achieve.getAchieveId();
        } else {
            log.error("审核id为{}的achieve失败",achieve.getAchieveId());
            throw new BizException("审核失败id为[id=" + achieve.getAchieveId() + "]");
        }
    }

    @Override
    public int insertAchieve(Achieve achieve) {
        achieve.setPubTime(LocalDateTime.now());
        achieve.setState(Achieve.CHECK);
        log.info("正在插入achieve");
        if (super.save(achieve)) {
            log.info("插入achieve成功,id为{}",achieve.getAchieveId());
            return achieve.getAchieveId();
        } else {
            log.error("插入achieve失败");
            throw new BizException("添加失败");
        }
    }

    @Transactional
    @Override
    public int deleteAchieveById(int id,int userId) {
        log.info("正在删除id为{}的achieve",id);
        QueryWrapper<Achieve> queryWrapper=new QueryWrapper<Achieve>().select("u_id").eq("achieve_id",id);
        Achieve achieve=super.getOne(queryWrapper);
        //判断是否是该用户的成果
        if(achieve!=null&&achieve.getUId()!=userId){
            log.info("该{}成果不是{}用户的，无法删除",id,userId);
            throw new BizException("该成果不是这个用户的，无法删除");
        }
        //删除成果附件文件
        List<AAccessory> aAccessoryByAId = aAccessoryService.getAAccessoryByAId(id);
        for(AAccessory aAccessory:aAccessoryByAId){
            fileService.delete(aAccessory.getAccessoryName());
        }
        collectService.deleteCollectByForeignId(id,Collect.ACHIEVE_TYPE);
        if (super.removeById(id)) {
            log.info("删除id为{}的achieve成功",id);
            return id;
        } else {
            log.error("删除id为{}的achieve失败",id);
            throw new BizException("删除失败[id=" + id + "]");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateAchieve(Achieve achieve) {
        log.info("正在更新id为{}的achieve",achieve.getAchieveId());
        Achieve user=super.getById(achieve.getAchieveId());
        //设置状态
        achieve.setState(Achieve.CHECK);
        if(!user.getUId().equals(achieve.getUId())){
            log.info("该{}成果不是{}用户的，无法修改",achieve.getAchieveId(),achieve.getUId());
            throw new BizException("该成果不是这个用户的，无法删除");
        }
        if (super.updateById(achieve)) {
            log.info("更新d为{}的achieve成功",achieve.getAchieveId());
            return achieve.getAchieveId();
        } else {
            log.error("更新id为{}的achieve失败",achieve.getAchieveId());
            throw new BizException("更新失败[id=" + achieve.getAchieveId() + "]");
        }
    }

    @Override
    public int importAchieve(String fileName, MultipartFile file,User user) throws IOException {
        log.info("开始导入文件，批量增加成果");
        if (!ExcelUtil.validateExcel(fileName)){
            log.error("上传文件格式错误,导入成果失败");
            throw new BizException("上传文件格式错误");
        }
        //03和07之后的文件命名不一样，需分别开来
        boolean isExcel2003 = false;
        if (ExcelUtil.isExcel2003(fileName)){
            isExcel2003 = true;
        }
        InputStream is = file.getInputStream();
        Workbook wb = null;
        //根据不同的文件生成不同的对象
        if (isExcel2003) {
            wb = new HSSFWorkbook(is);
        } else {
            wb = new XSSFWorkbook(is);
        }
        Sheet sheet = wb.getSheetAt(0);
        List<Achieve> achieves = new ArrayList<>();
        //r从1开始，因为数据是从第二行开始记录
        for (int r = 1; r <= sheet.getLastRowNum(); r++) {
            Row row = sheet.getRow(r);
            if (row == null) {
                continue;
            }
            Achieve achieve = new Achieve();
            //从上往下是 成果名称、项目负责人、成果类型、行业分类、成果简介、专利情况
            if (row.getCell(0) == null){
                break;
            }
            achieve.setAchieveName(row.getCell(0) != null ? row.getCell(0).getStringCellValue() : "");
            achieve.setAchieveLeader(row.getCell(1) != null ? row.getCell(1).getStringCellValue() : "");
            achieve.setAchieveType(row.getCell(2) != null ? row.getCell(2).getStringCellValue() : "");
            achieve.setAchieveIndustry(row.getCell(3) != null ? row.getCell(3).getStringCellValue() : "");
            achieve.setAchieveIntro(row.getCell(4) != null ? row.getCell(4).getStringCellValue() : "");
            achieve.setPatent(row.getCell(5) != null ? row.getCell(5).getStringCellValue() : "");
            achieve.setPubTime(LocalDateTime.now());
            achieves.add(achieve);
        }
        for (Achieve achieve:achieves) {
            //如果是管理员导入则审核状态设置为已通过
            if (user.getState() == User.ADMIN){
                achieve.setState(Achieve.PASS);
            }
            //成果名和项目负责人作为唯一标识
            Achieve isHave = this.getAchieveByAchieveNameAndAchieveLeader(achieve.getAchieveName(),achieve.getAchieveLeader());
            if (isHave!=null){
                //如果存在此成果则覆盖
                achieve.setAchieveId(isHave.getAchieveId());
                super.updateById(achieve);
            }else{
                achieve.setUId(user.getUserId());
                super.save(achieve);
            }
        }
        log.info("导入成果成功，共导入{}条数据",achieves.size());
        return achieves.size();
    }

  //  @Autowired


    @Override
    public int UncheckedNum() {
        log.info("正在查询未审核的数量");
/*
        LambdaQueryWrapper<Achieve> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(Achieve::getState);
       return  this.getBaseMapper().selectObjs(lambdaQueryWrapper).stream()
                                .map(o -> (Integer) o).collect(Collectors.toList()).size(); //getBaseMapper().selectBatchIds(Arrays.asList(0));  // (List<Achieve>) super.getMap();
       */
        QueryWrapper<Achieve> queryWrapper=new QueryWrapper<Achieve>().eq("state",0);
        List<Achieve> achieveList = this.getBaseMapper().selectList(queryWrapper);
        return achieveList.size();
    }

}
